package drive

import (
	"encoding/json"
	"time"

	"github.com/boltdb/bolt"
)

/**
* Boltdb结构体
 */
type Boltdb struct {
	Key   string `json:"key"`
	Value []byte `json:"value"`
	Expire int64 `json:"expire"`
}

/**
* 写入单个boltdb
* bucket bucket名称
* key 键名
* val 值
 */
func BoltdbPut(bucket string, key string, val []byte, expire int64) error {
	db, err := bolt.Open("data.db", 0600, nil)
	if err != nil {
		return err
	}

	defer db.Close()

	err = db.Update(func(tx *bolt.Tx) error {
		b, err := tx.CreateBucketIfNotExists([]byte(bucket))
		if err != nil {
			return err
		}
		putk,_:= json.Marshal(Boltdb{
			Key:key,
			Value:val,
			Expire:time.Now().Unix()+expire,
		})
		err = b.Put([]byte(key), putk)
		if err != nil {
			return err
		}
		return nil
	})
	return err
}

/**
* 读取单个boltdb
* bucket bucket名称
* key 键名
 */
func BoltdbRead(bucket, key string) []byte {
	db, err := bolt.Open("data.db", 0600, nil)
	if err != nil {
		return nil
	}
	defer db.Close()
	var v []byte
	db.View(func(tx *bolt.Tx) error {
		// Assume bucket exists and has keys
		b := tx.Bucket([]byte(bucket))
		if b == nil {
			return nil
		}
		//内容
		c := b.Get([]byte(key))
		data:=Boltdb{}
		err:=json.Unmarshal(c,&data)
		if err!=nil || data.Key==""{
			return nil
		}
		
		//过期检查
		if data.Expire<=time.Now().Unix(){
			return nil
		}
		//计算大小
		v = make([]byte, len(data.Value))
		copy(v, data.Value)

		return nil
	})
	if len(v) == 0 {
		return nil
	}
	return v
}

/**
* 更据bucket读取boltdb列表
* bucket bucket名称
 */
func BoltdbReadList(bucket string) ([]Boltdb, int) {
	db, err := bolt.Open("data.db", 0600, nil)
	if err != nil {
		return nil, 0
	}
	defer db.Close()

	var list []Boltdb
	total := 0
	db.View(func(tx *bolt.Tx) error {
		// Assume bucket exists and has keys
		b := tx.Bucket([]byte(bucket))
		if b == nil {
			return nil
		}
		c := b.Cursor()
		for k, v := c.First(); k != nil; k, v = c.Next() {
			var  d Boltdb
			err:=json.Unmarshal(v,&d)
			if err==nil{
				list = append(list, d)
				total++
			}
			
		}
		return nil
	})
	return list, total
}

/**
* 删除boltdb
* bucket bucket名称
* key 键名
 */
func BoltdbDel(bucket, key string) error {
	db, err := bolt.Open("data.db", 0600, nil)
	if err != nil {
		return err
	}
	defer db.Close()

	db.Update(func(tx *bolt.Tx) error {
		// Assume bucket exists and has keys
		b := tx.Bucket([]byte(bucket))
		if b == nil {
			return nil
		}
		err := b.Delete([]byte(key))
		if err != nil {
			return err
		}
		return nil
	})
	return nil
}

/**
* 删除过期boltdb
* bucket bucket名称
* key 键名
 */
func BoltdbExpire(bucket string) error {
	db, err := bolt.Open("data.db", 0600, nil)
	if err != nil {
		return nil
	}
	defer db.Close()
	db.Update(func(tx *bolt.Tx) error {
		// Assume bucket exists and has keys
		b := tx.Bucket([]byte(bucket))
		if b == nil {
			return nil
		}
		c := b.Cursor()
		
		for k, v := c.First(); k != nil; k, v = c.Next() {
			//println(string(k[7:]))
			var  d Boltdb
			err:=json.Unmarshal(v,&d)
			if err != nil {
				break
			}
			//过期检查
			if d.Expire<=time.Now().Unix(){
				err:=b.Delete([]byte(d.Key))
				if err != nil {
					break
				}
			}
		}
		return nil
	})
	return nil
}
/**
* 删除重复，同一用户重复
* bucket bucket名称
* key 键名
 */

func BoltdbRepeat(bucket string) error {
	db, err := bolt.Open("data.db", 0600, nil)
	if err != nil {
		return nil
	}
	defer db.Close()
	list := make(map[int]Token)
	//total := 0
	db.Update(func(tx *bolt.Tx) error {
		// Assume bucket exists and has keys
		b := tx.Bucket([]byte(bucket))
		c := b.Cursor()
		for k, v := c.First(); k != nil; k, v = c.Next() {
			var  d Boltdb
			err:=json.Unmarshal(v,&d)
			if err != nil {
				break
			}
			expire_time, _ := time.ParseInLocation("2006-01-02 15:04:05", string(d.Expire), time.Local)

			u := Token{}
			json.Unmarshal(d.Value, &u)
			if v2, ok := list[u.Id]; ok {
				if v2.CreateAt.Before(u.CreateAt) {
					u.CreateAt = expire_time
					list[u.Id] = u
					b.Delete([]byte(v2.UserName))
				} else {
					b.Delete([]byte(string(k)))
				}
			} else {
				u.CreateAt = expire_time
				u.UserName = string(k)
				list[u.Id] = u
			}

		}
		return nil
	})
	return nil
}
